
#include "functions.h"

static int
getcmp( void * tag, List * args )
{
    RuleEngineContext * r = tag;

    if( list_length(args) != 2 )
    {
        evaluator_emit_error( r->eval, QL_ERR_INVALID_ARGUMENTS );
    }

    return objcmp( args->car, args->cdr->car );
}



Obj *
f_eq( void * tag, List * args )
{
    return (getcmp(tag, args) == 0 ? g_t_obj : g_nil_obj);
}

Obj *
f_greater( void * tag, List * args )
{
    return (getcmp(tag, args) > 0 ? g_t_obj : g_nil_obj);
}

Obj *
f_less( void * tag, List * args )
{
    return (getcmp(tag, args) < 0 ? g_t_obj : g_nil_obj);
}


Obj *
f_greater_or_equal( void * tag, List * args )
{
    return (getcmp(tag, args) >= 0 ? g_t_obj : g_nil_obj);
}

Obj *
f_less_or_equal( void * tag, List * args )
{
    return (getcmp(tag, args) <= 0 ? g_t_obj : g_nil_obj);
}

Obj *
f_if( void * tag, List * args )
{
    RuleEngineContext * r = tag;
    size_t              len = list_length( args );

    if( len < 2 || len > 3 )
    {
        evaluator_emit_error( r->eval, QL_ERR_INVALID_ARGUMENTS );
    }

    if( internal_evaluate(r->eval, args->car)->type == OBJ_NIL )
    {
        // else block is present?
        if( len == 3 )
        {
            return internal_evaluate( r->eval, args->cdr->cdr->car );
        }

        return g_nil_obj;
    }

    return internal_evaluate( r->eval, args->cdr->car );
}

Obj *
f_cond( void * tag, List * args )
{
    RuleEngineContext * r = tag;

    if( 0 != args && 0 != args->car )
    {
        do
        {
            List *  cond_action = (List *)args->car;
            if( cond_action->type != OBJ_LIST || list_length(cond_action) != 2 )
            {
                evaluator_emit_error( r->eval, QL_ERR_INVALID_ARGUMENTS );
            }

            if( internal_evaluate(r->eval, cond_action->car)->type != OBJ_NIL )
            {
                return internal_evaluate( r->eval, cond_action->cdr->car );
            }
        }
        while( 0 != args );
    }

    return g_nil_obj;
}
